﻿using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using mozhi.smarterp.Finance.Files.Repository;
using Mozhi.Abp.Core.Files;
using Mozhi.Abp.Domain.BasicData.Repositories;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Domain.Services;
using Volo.Abp.Guids;

namespace mozhi.smarterp.Finance.Files.Services
{
    public class FileManager : DomainService
    {
        private IConfiguration _configuration;
        private IFileRepository _fileRepository;
        private IOrganizationRepository _organizationRepository;
        private IGuidGenerator _guidGenerator;

        public FileManager(IFileRepository fileRepository, IGuidGenerator guidGenerator , IServiceProvider serviceProvider)
        {
            _configuration = serviceProvider.GetService(typeof(IConfiguration)) as IConfiguration;
            _organizationRepository = serviceProvider.GetService(typeof(IOrganizationRepository)) as IOrganizationRepository;
            _fileRepository = fileRepository;
            _guidGenerator = guidGenerator;
        }

        public async Task<File> CreateAsync(IFormFile formFile)
        {
            var organization = await _organizationRepository.GetAsync();

            var fileClient = FileClientFactory.Instance(_configuration, organization.Id);

            var name = Path.GetFileNameWithoutExtension(formFile.FileName);
            var extension = Path.GetExtension(formFile.FileName);
            var fileName = Path.GetFileName(formFile.FileName);
            var size = (int)formFile.Length;
            var contentType = formFile.ContentType;

            Validate(extension, size);

            Tuple<bool, string> fileUploadResult = null;

            using (var stream = formFile.OpenReadStream())
            {
                fileUploadResult = await fileClient.UploadFileAsync(stream , fileName);
            }

            if (fileUploadResult == null || fileUploadResult.Item1 == false)
                throw new UserFriendlyException($"文件：{name}上传失败", "100000");

            var file = new File(_guidGenerator.Create(), name, size, extension, fileUploadResult.Item2 , contentType);


            file = await _fileRepository.InsertAsync(file);


            return file;

        }


        public async Task<File> CreateAsync(string fileName , string contentType , Stream stream)
        {
            var organization = await _organizationRepository.GetAsync();

            var fileClient = FileClientFactory.Instance(_configuration, organization.Id);

            var name = Path.GetFileNameWithoutExtension(fileName);
            var extension = Path.GetExtension(fileName);
            var size = (int)stream.Length;
           
            Validate(extension, size);

            Tuple<bool, string> fileUploadResult = null;

            fileUploadResult = await fileClient.UploadFileAsync(stream, fileName);

            if (fileUploadResult == null || fileUploadResult.Item1 == false)
                throw new UserFriendlyException($"文件：{name}上传失败", "100000");

            var file = new File(_guidGenerator.Create(), name, size, extension, fileUploadResult.Item2, contentType);


            file = await _fileRepository.InsertAsync(file);


            return file;
        }


        public async Task<Tuple<Stream, string, string>> DownloadFileAsync(Guid id)
        {
            var file = await _fileRepository.FindAsync(id);

            if (file == null)
                throw new UserFriendlyException($"文件:{id}不存在", "100000");

            var organization = await _organizationRepository.GetAsync();

            var fileClient = FileClientFactory.Instance(_configuration, organization.Id);


            var stream = await fileClient.DownloadFileAsync(file.RemotePath);

            stream.Position = 0;

            return new Tuple<Stream, string, string>(stream, file.ContentType, file.FileName + file.FileExtension);

        }

        #region
        private void Validate(string extension , int fileSize)
        {
            var limitSize = int.Parse(_configuration["File:LimitSize"]);

            var format = _configuration["File:Format"];

            if (fileSize == 0)
                throw new UserFriendlyException("不能上传空文件", "100000");

            if ((fileSize / 1048576) > limitSize)
                throw new UserFriendlyException($"文件不能大于{limitSize}M", "100000");

            var fileSizeSplits = format.Split('|');

            var tempExtension = extension.Replace(".", "");

            if (fileSizeSplits.Length > 0 && !fileSizeSplits.Contains(tempExtension.ToLower()) && !fileSizeSplits.Contains(tempExtension.ToUpper()))
                throw new UserFriendlyException($"文件格式不是{format}", "100000");
        }
        #endregion
    }
}
